﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;

namespace Zeus.DataTrans.Serialize.Memory
{
    public static class MemorySerializer
    {
        /// <summary>
        /// 用序列化和反序列化的方法来实现对对象的深拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T DeepCopy<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                //序列化成流
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                //反序列化成对象
                retval = bf.Deserialize(ms);
                ms.Close();
            }

            return (T)retval;
        }

        /// <summary>
        /// Serialize a generic object to stream
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static MemoryStream SerializeToMemory<T>(T obj)
        {
            // Construct a stream that is to hold the serialized objects
            MemoryStream stream = new MemoryStream();

            // Construct a serialization formatter that does all the hard work
            BinaryFormatter formatter = new BinaryFormatter();

            // Tell the formatter to serialize the objects into the stream
            formatter.Serialize(stream, obj);

            // Return the stream of serialized objects back to the caller
            return stream;
        }

        /// <summary>
        /// Deserialize a generic object from stream
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static T DeserializeFromMemory<T>(Stream stream)
        {
            // Construct a serialization formatter that does all the hard work
            BinaryFormatter formatter = new BinaryFormatter();

            // Tell the formatter to deserialize the objects from the stream
            return (T)formatter.Deserialize(stream);
        }

        /// <summary>
        /// Deep Clone a generic object by stream serialization
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        public static T DeepClone<T>(T original)
        {
            // Construct a temporary memory stream
            using (MemoryStream stream = new MemoryStream())
            {

                // Construct a serialization formatter that does all the hard work
                BinaryFormatter formatter = new BinaryFormatter();

                // This line is explained in this chapter's “Streaming Contexts” section 
                formatter.Context = new StreamingContext(StreamingContextStates.Clone);

                // Serialize the object graph into the memory stream
                formatter.Serialize(stream, original);

                // Seek back to the start of the memory stream before deserializing
                stream.Position = 0;

                // Deserialize the graph into a new set of objects and 
                // return the root of the graph (deep copy) to the caller
                return (T)formatter.Deserialize(stream);
            }
        }
    }
}
